package com.bosssoft.g1.gateway.authorization;

import com.bosssoft.g1.common.data.vo.CommonResponse;
import com.bosssoft.g1.gateway.service.FeignServiceClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authorization.AuthorizationDecision;
import org.springframework.security.authorization.ReactiveAuthorizationManager;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.server.authorization.AuthorizationContext;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;

import javax.annotation.PostConstruct;
import java.net.URI;
import java.util.ArrayList;
import java.util.List;

/**
 * 鉴权管理器，用于判断是否有资源的访问权限
 * Created by macro on 2020/6/19.
 */
@Component
public class AuthorizationManager implements ReactiveAuthorizationManager<AuthorizationContext> {

    List<String> authoritiesList = new ArrayList<>();

    @Autowired
    private FeignServiceClient feignServiceClient;

    @PostConstruct
    private void initData() {
        authoritiesList = new ArrayList<>();
        authoritiesList.add("/oauth/token");
        authoritiesList.add("/auth/oauth/token");
        authoritiesList.add("/api/hello");
        authoritiesList.add("/api/user/currentUser");
    }

    @Override
    public Mono<AuthorizationDecision> check(Mono<Authentication> mono, AuthorizationContext authorizationContext) {
        // 获取当前请求的URI路径
        URI uri = authorizationContext.getExchange().getRequest().getURI();
        String path = uri.getPath();
        System.out.println("path 是 " + path);
        // 检查当前路径是否在 authoritiesList 中
        boolean isAuthorizedPath = authoritiesList.contains(path);

        // 获取请求中的token
        String token = authorizationContext.getExchange().getRequest().getHeaders().getFirst("Authorization");

        CommonResponse<Boolean> booleanCommonResponse = feignServiceClient.checkToken(token);
        boolean tokenValid = booleanCommonResponse.getBody();

        // 如果路径在 authoritiesList 中，则进行权限验证
        if (isAuthorizedPath) {
            return mono
                    .filter(Authentication::isAuthenticated)  // 过滤出已认证的用户
                    .map(auth -> new AuthorizationDecision(true))  // 授权通过
                    .defaultIfEmpty(new AuthorizationDecision(false));  // 未认证用户拒绝访问
        } else {
            if (tokenValid) {
                return Mono.just(new AuthorizationDecision(true));  // token有效，授权通过
            } else {
                return Mono.just(new AuthorizationDecision(false));  // token无效，拒绝访问
            }
        }
    }
}